package com.bob.shirodemo.base.shiro;

import com.bob.shirodemo.base.spring.SpringCacheManagerWrapper;
import com.bob.shirodemo.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
import org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.ShiroHttpSession;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

import java.util.ArrayList;
import java.util.LinkedHashMap;

@Configuration
public class ShiroConfiguration {


    //读取ehcache配置文件
    @Bean
    public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() {
        EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
        ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml")); //如果不配置，就是默认
        return ehCacheManagerFactoryBean;
    }


    /**
     * ehcache缓存管理器
     * @param ehCacheManagerFactoryBean
     * @return
     */
    @Bean
    public EhCacheCacheManager ehCacheCacheManager(EhCacheManagerFactoryBean ehCacheManagerFactoryBean) {
        EhCacheCacheManager ehCacheCacheManager = new EhCacheCacheManager();
        ehCacheCacheManager.setCacheManager(ehCacheManagerFactoryBean.getObject());
        return ehCacheCacheManager;
    }


    /**
     * 包装Spring cache抽象
     * @param ehCacheCacheManager
     * @return
     */
    @Bean
    public CacheManager cacheManager(EhCacheCacheManager ehCacheCacheManager) {
        SpringCacheManagerWrapper springCacheManagerWrapper = new SpringCacheManagerWrapper();
        springCacheManagerWrapper.setCacheManager(ehCacheCacheManager);
        return springCacheManagerWrapper;
    }

    /**
     * 重试限制凭证匹配器：用来实现凭证的校验规则，比如说重试多少次，比如密码的加密验证
     * @param cacheManager
     * @return
     */
    @Bean
    protected RetryLimitHashedCredentialsMatcher credentialsMatcher(CacheManager cacheManager) {
        RetryLimitHashedCredentialsMatcher credentialsMatcher = new RetryLimitHashedCredentialsMatcher(cacheManager);
        //设置散列算法（必须要设置的参数） 这里设置的是md5
        credentialsMatcher.setHashAlgorithmName("md5");
        credentialsMatcher.setHashIterations(2); //散列迭代次数，需要和生成密码时的意义；
        return credentialsMatcher;
    }

    /**
     * 自定义用户Realm,用来从数据源获得数据
     * @param userService
     * @return
     */
    @Bean
    public UserRealm realm(UserService userService, CacheManager cacheManager, RetryLimitHashedCredentialsMatcher retryLimitHashedCredentialsMatcher) {
        UserRealm userRealm = new UserRealm();
        userRealm.setUserService(userService);
        //验证机制
        userRealm.setCredentialsMatcher(retryLimitHashedCredentialsMatcher);
        userRealm.setAuthenticationCacheName("authenticationCache"); //这个是缓存认证信息的key，和ehcache.xml中配置要一致
        userRealm.setAuthorizationCacheName("authorizationCache"); //这个是缓存授权信息的key，和ehcache.xml中配置要一致
        //这条配置一定要在上面两条配置之后，不然上面的两个key的设置是没有用的
        userRealm.setCacheManager(cacheManager);
        return userRealm;
    }

    /**
     * 配置Shiro的安全管理器
     * @param userRealm
     * @param cacheManager
     * @return
     */
    @Bean
    public SecurityManager securityManager(CacheManager cacheManager, UserRealm userRealm){
        //1.ingest our shiro.ini file which is located at the root of the classpath
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //会话管理
        securityManager.setRealm(userRealm);
        securityManager.setCacheManager(cacheManager);
        ShiroSessionManager shiroSessionManager = new ShiroSessionManager();
//        sessionManager.setSessionIdCookie(new SimpleCookie("ddfsdfsdfs"));
        ArrayList arrayList = new ArrayList();
        arrayList.add(new MySessionListener());
        shiroSessionManager.setSessionListeners(arrayList);
        securityManager.setSessionManager(shiroSessionManager);
        SecurityUtils.setSecurityManager(securityManager);
        return securityManager;
    }

    //spring整合shiro凭证匹配器
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager manager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(manager);
        return advisor;
    }


    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(securityManager);
//        bean.getFilters().put("shiroResourceFilter", shiroResourceFilter);
        //配置登录的url和登录成功的url
        bean.setLoginUrl("/no_login"); //未登录时，跳转的请求
//		bean.setSuccessUrl("/home");
        //配置访问权限
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
//		filterChainDefinitionMap.put("/jsp/login.jsp*", "anon"); //表示可以匿名访问
//		filterChainDefinitionMap.put("/loginUser", "anon");
		filterChainDefinitionMap.put("/login","anon");
//		filterChainDefinitionMap.put("/error","anon");
//		filterChainDefinitionMap.put("/logout*","anon");
//		filterChainDefinitionMap.put("/jsp/error.jsp*","anon");
//		filterChainDefinitionMap.put("/jsp/index.jsp*","authc");
        ;
//		filterChainDefinitionMap.put("/user/info", "authc");//表示需要认证才可以访问
        filterChainDefinitionMap.put("/*", "authc");//表示需要认证才可以访问
//        filterChainDefinitionMap.put("/**", "shiroResourceFilter");//表示需要认证才可以访问
//		filterChainDefinitionMap.put("/*.*", "authc");
        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return bean;
    }

//    @Bean
//    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager, ShiroResourceFilter shiroResourceFilter) {
//        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//        bean.setSecurityManager(manager);
//        bean.getFilters().put("shiroResourceFilter", shiroResourceFilter);
//        //配置登录的url和登录成功的url
//        bean.setLoginUrl("/no_login"); //未登录时，跳转的请求
////		bean.setSuccessUrl("/home");
//        //配置访问权限
//        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
////		filterChainDefinitionMap.put("/jsp/login.jsp*", "anon"); //表示可以匿名访问
////		filterChainDefinitionMap.put("/loginUser", "anon");
////		filterChainDefinitionMap.put("/user/login","anon");
////		filterChainDefinitionMap.put("/error","anon");
////		filterChainDefinitionMap.put("/logout*","anon");
////		filterChainDefinitionMap.put("/jsp/error.jsp*","anon");
////		filterChainDefinitionMap.put("/jsp/index.jsp*","authc");
//        ;
////		filterChainDefinitionMap.put("/user/info", "authc");//表示需要认证才可以访问
//        filterChainDefinitionMap.put("/*", "authc");//表示需要认证才可以访问
//        filterChainDefinitionMap.put("/**", "shiroResourceFilter");//表示需要认证才可以访问
////		filterChainDefinitionMap.put("/*.*", "authc");
//        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
//        return bean;
//    }

//    /**
//     * 会话ID生成器
//     * @return
//     */
//    @Bean
//    public JavaUuidSessionIdGenerator javaUuidSessionIdGenerator() {
//        return new JavaUuidSessionIdGenerator();
//    }
//
//    /**
//     *  会话DAO
//     * @param javaUuidSessionIdGenerator
//     * @return
//     */
//    @Bean
//    public EnterpriseCacheSessionDAO enterpriseCacheSessionDAO(JavaUuidSessionIdGenerator javaUuidSessionIdGenerator) {
//        EnterpriseCacheSessionDAO enterpriseCacheSessionDAO = new EnterpriseCacheSessionDAO();
//        enterpriseCacheSessionDAO.setSessionIdGenerator(javaUuidSessionIdGenerator);
//        //这个默认就是这个，不配置也是可以
//        enterpriseCacheSessionDAO.setActiveSessionsCacheName(EnterpriseCacheSessionDAO.ACTIVE_SESSION_CACHE_NAME);
//        return enterpriseCacheSessionDAO;
//    }
//
//    /**
//     * 会话管理器
//     * @return
//     */
//    @Bean
//    public DefaultSessionManager defaultSessionManager(EnterpriseCacheSessionDAO enterpriseCacheSessionDAO, QuartzSessionValidationScheduler quartzSessionValidationScheduler) {
//        DefaultSessionManager defaultSessionManager = new DefaultSessionManager();
//        defaultSessionManager.setGlobalSessionTimeout(1800000);
//        defaultSessionManager.setSessionValidationScheduler(quartzSessionValidationScheduler);
//        defaultSessionManager.setDeleteInvalidSessions(true);
//        defaultSessionManager.setSessionValidationSchedulerEnabled(true);
//        defaultSessionManager.setSessionDAO(enterpriseCacheSessionDAO);
//        return defaultSessionManager;
//    }
//
//    @Bean
//    public QuartzSessionValidationScheduler quartzSessionValidationScheduler() {
//        QuartzSessionValidationScheduler quartzSessionValidationScheduler = new QuartzSessionValidationScheduler();
////		quartzSessionValidationScheduler.setSessionManager(defaultSessionManager);
//        quartzSessionValidationScheduler.setSessionValidationInterval(1800000);
//        return quartzSessionValidationScheduler;
//    }

    /**
     * 资源过滤器
     * @return
     */
//    @Bean
//    public ShiroResourceFilter shiroResourceFilter() {
//        ShiroResourceFilter shiroResourceFilter = new ShiroResourceFilter();
////		shiroResourceFilter.init();
//        return shiroResourceFilter;
//    }






}
